﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.Web;
using System.Linq;
using Microsoft.SharePoint;

using Kiiro.Common.Entities;
using Kiiro.Common.Utility;
using Kiiro.Model;

namespace Kiiro.WebServices
{
    public static class WebServicesHelper
    {
        private static string universalTime = System.Globalization.DateTimeFormatInfo.InvariantInfo.UniversalSortableDateTimePattern;

        public static int ProjectId ( string path )
        {
            string projectId = string.Empty;

            string [ ] pathParts = path.Split ( "/".ToCharArray ( ), StringSplitOptions.RemoveEmptyEntries );

            projectId = pathParts [ pathParts.Length - 1 ];
            projectId = projectId.Split ( "_".ToCharArray ( ), StringSplitOptions.None ) [ 0 ];

            return int.Parse ( projectId );
        }

        public static Work XmlToWork(XmlNode task, Dictionary<string, int> projectUsers)
        {
            Work work = new Work();
            
            XmlNode assignedToList = task.SelectSingleNode("AssignedToList");
            foreach (XmlNode assignedTo in assignedToList.ChildNodes)
            {
                if (projectUsers.Keys.Contains(assignedTo.InnerText))
                    work.AssignedToList.Add(projectUsers[assignedTo.InnerText]);
            }

            work.ParentTasks = task.SelectSingleNode("ParentTasks") != null ? task.SelectSingleNode("ParentTasks").InnerText : null;
            work.AssignedWork = task.SelectSingleNode("AssignedWork") != null ? float.Parse(task.SelectSingleNode("AssignedWork").InnerText) : 0;
            work.PercentageComplete = task.SelectSingleNode("PercentageComplete") != null ? float.Parse(task.SelectSingleNode("PercentageComplete").InnerText) : 0;
            work.Title = task.SelectSingleNode("Title") != null ? task.SelectSingleNode("Title").InnerText : null;
            if (string.IsNullOrEmpty(work.Title.Trim()))
                work.Title = "untitled";
            work.Description = task.SelectSingleNode("Description") != null ? task.SelectSingleNode("Description").InnerText : null;
            work.StatusNote = task.SelectSingleNode("StatusNote") != null ? task.SelectSingleNode("StatusNote").InnerText : null;
            work.StartDate = task.SelectSingleNode("StartDate") != null ? DateTime.Parse(task.SelectSingleNode("StartDate").InnerText).ToUniversalTime() : default(DateTime);
            work.EndDate = task.SelectSingleNode("EndDate") != null ? DateTime.Parse(task.SelectSingleNode("EndDate").InnerText).ToUniversalTime() : default(DateTime);
            work.PlanId = task.SelectSingleNode("PlanId") != null ? int.Parse(task.SelectSingleNode("PlanId").InnerText) : 0;
            XmlNode key = task.SelectSingleNode("Key");
            if (key != null)
            {
                if (key.InnerText == "updated")
                    work.EditType = EditType.Updated;
                else if (key.InnerText == "deleted")
                    work.EditType = EditType.Deleted;
                else if (key.InnerText == "added")
                    work.EditType = EditType.Created;
            }
            int midoriId = 0;
            if(task.SelectSingleNode("MidoriId") != null)
                int.TryParse(task.SelectSingleNode("MidoriId").InnerText, out midoriId);
            work.Id = midoriId;

            if (work.EditType == EditType.Created && work.Id > 0)
                work.EditType = EditType.Updated;

            if (work.PercentageComplete == 100)
                work.Status = StatusType.Completed;
            else if (work.PercentageComplete <= 0)
                work.Status = StatusType.NotStarted;
            else
                work.Status = StatusType.InProgress;

            work.WorkItemType = WorkType.Task;

            work.IsFromProjectPlan = true;

            return work;
        }

        public static void PopulateWork ( Work to, Work from )
        {
            to.AssignedToList = from.AssignedToList;
            to.AssignedWork = from.AssignedWork;
            to.Description = from.Description;
            to.EndDate = from.EndDate;
            to.ParentTasks = from.ParentTasks;
            to.PercentageComplete = from.PercentageComplete;
            to.StartDate = from.StartDate;
            to.Status = from.Status;
            to.StatusNote = from.StatusNote;
            to.Title = from.Title;
            to.WorkItemType = from.WorkItemType;
            to.PlanId = from.PlanId;
        }

        internal static void PopulateProject(Project project, XmlDocument xmlProject)
        {
            project.StartDate = xmlProject.DocumentElement.SelectSingleNode("StartDate") != null ? DateTime.Parse(xmlProject.DocumentElement.SelectSingleNode("StartDate").InnerText).ToUniversalTime() : default(DateTime);
            project.EndDate = xmlProject.DocumentElement.SelectSingleNode("EndDate") != null ? DateTime.Parse(xmlProject.DocumentElement.SelectSingleNode("EndDate").InnerText).ToUniversalTime() : default(DateTime);
            project.SummaryNote = xmlProject.DocumentElement.SelectSingleNode("SummaryNote") != null ? xmlProject.DocumentElement.SelectSingleNode("SummaryNote").InnerText : null;
            project.Description = xmlProject.DocumentElement.SelectSingleNode("Description") != null ? xmlProject.DocumentElement.SelectSingleNode("Description").InnerText : null;
        }

        internal static Dictionary<string, int> PopulateTeamDictionary(XmlDocument xmlProject, List<User> users)
        {
            Dictionary<string, int> projectUsers = new Dictionary<string, int>();

            XmlNode teamMembers = xmlProject.DocumentElement.SelectSingleNode("TeamMembers");
            foreach (XmlNode member in teamMembers.ChildNodes)
            {
                User user = users.Find(x => x.FullName.ToUpper().Trim() == member.InnerText.ToUpper().Trim());
                if(user != null)
                    projectUsers.Add(user.FullName, user.Id);
            }

            return projectUsers;
        }

        internal static Dictionary<int, string> PopulateTeamDictionary ( List<TeamMember> teamMembers, List<User> users )
        {
            Dictionary<int, string> teamDictionary = new Dictionary<int, string> ( );

            foreach ( TeamMember tM in teamMembers )
            {
                User user = users.Find(x => x.Id == tM.UserId);
                if (user != null)
                    teamDictionary.Add(user.Id, user.FullName);
            }

            return teamDictionary;
        }

        internal static void PopulateXmlTasks ( XmlDocument xmlMidori, List<Work> midoriTasks, Dictionary<int, string> projectUsers, Project project )
        {
            XmlElement midori = xmlMidori.DocumentElement;

            XmlNode tasks = CreateNode("Tasks", xmlMidori);

            foreach ( Work task in midoriTasks )
            {
                XmlNode xmlTask = CreateNode("Task", xmlMidori); 

                XmlNode assignedToList = CreateNode("AssignedToList", xmlMidori);
                foreach ( int assignedToId in task.AssignedToList )
                    assignedToList.AppendNewNode("AssignedTo", xmlMidori, projectUsers [ assignedToId ]);
                xmlTask.AppendChild(assignedToList);
                
                xmlTask.AppendNewNode("AssignedWork", xmlMidori, task.AssignedWork + "minutes");
                xmlTask.AppendNewNode("PercentageComplete", xmlMidori, task.PercentageComplete.ToString());
                xmlTask.AppendNewNode("Title", xmlMidori, task.Title);
                xmlTask.AppendNewNode("Description", xmlMidori, task.Description);
                xmlTask.AppendNewNode("StatusNote", xmlMidori, task.StatusNote);
                xmlTask.AppendNewNode("StartDate", xmlMidori, task.StartDate.ToString(universalTime));
                xmlTask.AppendNewNode("EndDate", xmlMidori, task.EndDate.ToString(universalTime));
                xmlTask.AppendNewNode("PlanId", xmlMidori, task.PlanId.ToString());
                xmlTask.AppendNewNode("MidoriId", xmlMidori, task.Id.ToString());

                tasks.AppendChild ( xmlTask );
            }

            midori.AppendChild ( tasks );
        }

        internal static void PopulateXmlProject ( XmlDocument xmlMidori, Project project )
        {
            XmlElement midori = xmlMidori.DocumentElement;
            XmlNode xmlProject = CreateNode("Project", xmlMidori);
            
            xmlProject.AppendNewNode("Description", xmlMidori, project.Description);
            xmlProject.AppendNewNode("SummaryNote", xmlMidori, project.SummaryNote);
            xmlProject.AppendNewNode("ProjectStart", xmlMidori, project.StartDate.ToString(universalTime));
            xmlProject.AppendNewNode("ProjectFinish", xmlMidori, project.EndDate.ToString(universalTime));

            midori.AppendChild ( xmlProject );
        }

        internal static void PopulateXmlTeam ( XmlDocument xmlMidori, Dictionary<int, string> teamMembers )
        {
            XmlElement midori = xmlMidori.DocumentElement;
            XmlNode xmlTeam = CreateNode("TeamMembers", xmlMidori);

            foreach ( string memberName in teamMembers.Values )
                xmlTeam.AppendNewNode("TeamMember", xmlMidori, memberName);

            midori.AppendChild ( xmlTeam );
        }

        internal static XmlNode CreateNode(string nodeName, XmlDocument xmlDoc)
        {
            XmlNode node = xmlDoc.CreateNode(XmlNodeType.Element, nodeName, "");
            return node;
        }      

        internal static void AppendNewNode(this XmlNode node, string nodeName, XmlDocument xmlDoc, string innerText)
        {
            XmlNode newNode = CreateNode(nodeName, xmlDoc);
            newNode.InnerText = innerText;
            node.AppendChild(newNode);
        }

        internal static Project GetProject ( string path )
        {
            Guid siteCollectionId = default ( Guid );
            string serverRelativeUrl = default ( string );
            SPHelpers.GetSiteCollectionIdAndServerRelativeUrl ( path, out siteCollectionId, out serverRelativeUrl );

            return ProjectsModel.GetByServerRelativeWebUrl ( siteCollectionId, serverRelativeUrl );
        }

        /// <summary>
        /// Checks if the given project URL already exists
        /// </summary>
        internal static bool DoesProjectExist(string projectURL, Guid siteCollectionId, string serverRelativeUrl)
        {
            bool exists = false;

            using (SPWeb portalWeb = SPHelpers.GetPortalWeb(siteCollectionId, serverRelativeUrl))
            {
                using (SPWeb web = portalWeb.Site.OpenWeb(SPHelpers.GetServerRelativeUrl(portalWeb) + "/" + projectURL))
                {
                    if (web.Exists)
                        exists = true;
                }
            }

            return (exists);
        }
    }
}

/*************************************************************************
 * 
 * $Log: /Internal Projects/Kiiro/Kiiro.WebServices/WebServicesHelper.cs $
 * 
 * 6     10/27/09 5:35p Adamw
 * accomodations for moving plan file to document library:
 * -added IsProjectPlan to Documents list
 * -changed regex in plugin to allow for new path
 * -changed the method to getProject to use GetByRelativeUrl
 * -changed web service urls to allow for new path
 * 
 * 5     27/10/09 2:37p Tobys
 * 
 * 4     10/02/09 10:46a Stefanf
 * 
 * 3     17/08/09 10:45a Camerons
 * Added check-in comments section
 * 
 ************************************************************************/